﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Sistema_de_Gestión_de_Correspondencia.Models;
using System.Web.Security;
using System.Data.Objects;
using System.IO;
using PagedList;

namespace Sistema_de_Gestión_de_Correspondencia.Controllers
{
    public class MailController : Controller
    {
        SGCEntities sgcDB = new SGCEntities();

        #region Constantes
        const int BANDEJA_BORRADOS = 5;
        const int BANDEJA_TODOS = 6;
        #endregion


        #region Exito
        public ActionResult Exito(int tipo)
        {
            ViewBag.tipo = tipo;
            return View();
        }
        #endregion

        #region Index
        // Ruta: /Mail/
        public ActionResult Index(int? page, string s = "", int tipo = 1)
        {
            Guid id = (Guid)Membership.GetUser().ProviderUserKey;
            ViewBag.S = s;
            ViewBag.Tipo = tipo;
            ModeloHome model = new ModeloHome();

            #region Sidebar
            model.modeloSidebar = new ModeloSidebar();
            model.modeloSidebar.TipoCorreo = sgcDB.TipoCorreos.Where(t => t.idTipoCorreo != BANDEJA_BORRADOS && t.idTipoCorreo != BANDEJA_TODOS).ToList();
            model.modeloSidebar.TipoCorreo = model.modeloSidebar.TipoCorreo.Concat(sgcDB.TipoCorreos.Where(t => t.idTipoCorreo == BANDEJA_BORRADOS || t.idTipoCorreo == BANDEJA_TODOS).ToList()).ToList();

            model.modeloSidebar.Active = sgcDB.TipoCorreos.Single(t => t.idTipoCorreo == tipo).nombre;

            if (Roles.IsUserInRole("Administrador"))
                model.modeloSidebar.Admin = true;
            else
                model.modeloSidebar.Admin = false;
            #endregion

            model.modeloMail = new ModeloMail();
            IQueryable<Correo> correos;
            if (tipo != BANDEJA_TODOS)
                correos = sgcDB.Correos.Where(c => c.FK_idUsuario == id && c.FK_idTipoCorreo == tipo);
            //correos = sgcDB.searchCorreosXUsuarioTipo(id, tipo).AsQueryable();
            else
                correos = sgcDB.Correos.Where(c => c.FK_idUsuario == id);

            if (!String.IsNullOrEmpty(s))
            {
                s = s.ToUpper();
                correos = correos.Where(c => c.asunto.ToUpper().Contains(s)
                    || c.bcc.ToUpper().Contains(s) || c.cc.ToUpper().Contains(s) || c.cuerpo.ToUpper().Contains(s)
                    || c.remitente.ToUpper().Contains(s) || c.remitido.ToUpper().Contains(s));
                ViewBag.cont = correos.Count();
            }

            correos = correos.OrderByDescending(c => c.fecha);

            int pageSize = 9;
            int pageNumber = (page ?? 1);
            model.modeloMail.Correo = correos.ToPagedList(pageNumber, pageSize);            
            return View(model);
        }
        #endregion

        #region Documentos Adjuntos
        // Ruta: /Mail/Download/id
        public ActionResult Download(int id)
        {
            DocumentoAdjunto da = sgcDB.DocumentoAdjuntoes.Single(d => d.idDocumento == id);
            if (da.Correo.FK_idUsuario != (Guid)Membership.GetUser().ProviderUserKey)
                return RedirectToAction("Index");

            return File(da.contenido, da.extension, da.nombre);
        }

        // Ruta: /Mail/EliminarDoc/id
        public ActionResult EliminarDoc(int id)
        {
            DocumentoAdjunto da = sgcDB.DocumentoAdjuntoes.Single(d => d.idDocumento == id);
            if (da.Correo.FK_idUsuario != (Guid)Membership.GetUser().ProviderUserKey)
                return RedirectToAction("Index");

            return View(da);
        }

        // Ruta: NA
        [HttpPost, ActionName("EliminarDoc")]
        public ActionResult EliminarDocConfirmed(int id)
        {
            DocumentoAdjunto da = sgcDB.DocumentoAdjuntoes.Single(d => d.idDocumento == id);
            int idCorreo = da.FK_idCorreo.Value;
            if (da.Correo.FK_idUsuario != (Guid)Membership.GetUser().ProviderUserKey)
                return RedirectToAction("Index");

            sgcDB.DocumentoAdjuntoes.DeleteObject(da);
            sgcDB.SaveChanges();
            return RedirectToAction("Edit", new { id = idCorreo });
        }
        #endregion     

        #region Detalle
        // Ruta: /Mail/Detalle/id
        public ActionResult Detalle(int id)
        {
            Correo correo = sgcDB.Correos.Single(c => c.idCorreo == id);
            ViewBag.tipo = sgcDB.TipoCorreos.Single(t => t.idTipoCorreo == correo.FK_idTipoCorreo).nombre;

            if (correo.FK_idUsuario != (Guid)Membership.GetUser().ProviderUserKey)
                return RedirectToAction("Index");

            return View(correo);
        }
        #endregion

        #region Edit
        // Ruta: /Mail/Edit/id
        public ActionResult Edit(int id)
        {
            #region Variables
            Correo correo = sgcDB.Correos.Single(c => c.idCorreo == id);
            #endregion

            if (correo.FK_idUsuario != (Guid)Membership.GetUser().ProviderUserKey)
                return RedirectToAction("Index");

            List<TipoCorreo> tipos = sgcDB.TipoCorreos.Where(t => t.idTipoCorreo != BANDEJA_TODOS).ToList();
            ViewBag.idTipoCorreo = new SelectList(tipos, "idTipoCorreo", "nombre", correo.FK_idTipoCorreo);
            ViewBag.medio = new SelectList(new[] 
            {
                new {idMedio = 0, nombre = "Electrónico"},
                new {idMedio = 1, nombre = "Físico"}
            }, "idMedio", "nombre", Convert.ToInt32(correo.medio_0E_1F));

            return View(correo);
        }

        // Ruta: /Mail/Edit
        [HttpPost]
        [ValidateInput(false)]
        public ActionResult Edit(Correo correo)
        {
            #region Variables
            int? idTipoCorreo = null;
            int? medio = null;
            #endregion

            #region Validaciones
            if (String.IsNullOrWhiteSpace(correo.remitente) || String.IsNullOrWhiteSpace(correo.remitido))
                ModelState.AddModelError("remitido", "Favor llenar los campos obligatorios");

            if (Request.Form["idTipoCorreo"] != "")
                idTipoCorreo = Convert.ToInt32(Request.Form["idTipoCorreo"]);
            else
                ModelState.AddModelError("idTipoCorreo", "Debe elegir un tipo");
            if (Request.Form["medio"] != "")
                medio = Convert.ToInt32(Request.Form["medio"]);
            else
                ModelState.AddModelError("medio", "Debe elegir un medio");
            #endregion

            if (ModelState.IsValid && idTipoCorreo.HasValue && medio.HasValue)
            {
                if (correo.asunto == null)
                    correo.asunto = "";
                if (correo.bcc == null)
                    correo.bcc = "";
                if (correo.cc == null)
                    correo.cc = "";
                if (correo.cuerpo == null)
                    correo.cuerpo = "";

                sgcDB.modCorreo(correo.idCorreo, (Guid)Membership.GetUser().ProviderUserKey, idTipoCorreo, 0, Convert.ToBoolean(medio), DateTime.Now, correo.asunto, correo.remitido, correo.cc, correo.bcc, correo.cuerpo, correo.remitente);

                #region Insertar Archivos
                if (Request.Files.Count > 0)
                {
                    HttpPostedFileBase archivo;
                    BinaryReader br;
                    for (int i = 0; i < Request.Files.Count; i++)
                    {
                        archivo = Request.Files[i];
                        br = new BinaryReader(archivo.InputStream);
                        if (archivo.ContentLength > 0)
                        {
                            sgcDB.addDocumentoAdjunto(correo.idCorreo, archivo.ContentType, archivo.ContentLength, br.ReadBytes(Convert.ToInt32(archivo.InputStream.Length)), archivo.FileName);
                        }
                    }
                }
                #endregion

                return RedirectToAction("Exito", new { tipo = Convert.ToInt32(Request.Form["idTipoCorreo"]) });
            }

            List<TipoCorreo> tipos = sgcDB.TipoCorreos.Where(t => t.idTipoCorreo != BANDEJA_BORRADOS).ToList();
            ViewBag.idTipoCorreo = new SelectList(tipos, "idTipoCorreo", "nombre", idTipoCorreo);
            ViewBag.medio = new SelectList(new[] 
            {
                new {idMedio = 0, nombre = "Electrónico"},
                new {idMedio = 1, nombre = "Físico"}
            }, "idMedio", "nombre", medio);
            return View();
        }
        #endregion

        #region Eliminar
        // Ruta: /Mail/Eliminar/id
        public ActionResult Eliminar(int id)
        {
            Correo correo = sgcDB.Correos.Single(c => c.idCorreo == id);

            if (correo.FK_idUsuario == (Guid)Membership.GetUser().ProviderUserKey)
            {
                if (correo.FK_idTipoCorreo != 5)
                    ViewBag.Mensaje = "¿Seguro que desea eliminar este correo? (Se movera a la bandeja Eliminados)";
                else
                    ViewBag.Mensaje = "¿Seguro que desea eliminar este correo del sistema? (Esta acción es irreversible)";
            }

            return View(correo);
        }

        // Ruta: NA
        [HttpPost, ActionName("Eliminar")]
        public ActionResult EliminarConfirmed(int id)
        {
            Correo correo = sgcDB.Correos.Single(c => c.idCorreo == id);

            if (correo.FK_idUsuario == (Guid)Membership.GetUser().ProviderUserKey)
            {
                if (correo.FK_idTipoCorreo != 5)
                    sgcDB.delCorreoTemporal(id);
                else
                    sgcDB.delCorreo(id);
            }
            return RedirectToAction("Exito", new { tipo = correo.FK_idTipoCorreo });            
        }
        #endregion

        #region Nuevo
        // Ruta: /Mail/Nuevo
        public ActionResult Nuevo()
        {
            List<TipoCorreo> tipos = sgcDB.TipoCorreos.Where(t => t.idTipoCorreo != BANDEJA_BORRADOS && t.idTipoCorreo != BANDEJA_TODOS).ToList();
            ViewBag.idTipoCorreo = new SelectList(tipos, "idTipoCorreo", "nombre");
            ViewBag.medio = new SelectList(new[] 
            {
                new {idMedio = 0, nombre = "Electrónico"},
                new {idMedio = 1, nombre = "Físico"}
            }, "idMedio", "nombre");
            return View();
        }

        // Ruta: /Mail/Nuevo
        [HttpPost]
        [ValidateInput(false)]
        public ActionResult Nuevo(Correo correo)
        {
            #region Variables
            int? idTipoCorreo = null;
            int? medio = null;
            #endregion

            #region Validaciones
            if (String.IsNullOrWhiteSpace(correo.remitente) || String.IsNullOrWhiteSpace(correo.remitido))
                ModelState.AddModelError("remitido", "Favor llenar los campos obligatorios");

            if (Request.Form["idTipoCorreo"] != "")
                idTipoCorreo = Convert.ToInt32(Request.Form["idTipoCorreo"]);
            else
                ModelState.AddModelError("idTipoCorreo", "Debe elegir un tipo");
            if (Request.Form["medio"] != "")
                medio = Convert.ToInt32(Request.Form["medio"]);
            else
                ModelState.AddModelError("medio", "Debe elegir un medio");
            #endregion

            if (ModelState.IsValid && idTipoCorreo.HasValue && medio.HasValue)
            {
                if (correo.asunto == null)
                    correo.asunto = "";
                if (correo.bcc == null)
                    correo.bcc = "";
                if (correo.cc == null)
                    correo.cc = "";
                if (correo.cuerpo == null)
                    correo.cuerpo = "";

                decimal idCorreo = sgcDB.addCorreo((Guid)Membership.GetUser().ProviderUserKey, idTipoCorreo, 0, Convert.ToBoolean(medio), DateTime.Now, correo.asunto, correo.remitido, correo.cc, correo.bcc, correo.cuerpo, correo.remitente).ElementAt(0).Value;
                
                #region Insertar Archivos
                if (Request.Files.Count > 0)
                {
                    HttpPostedFileBase archivo;
                    BinaryReader br;
                    for (int i = 0; i < Request.Files.Count; i++)
                    {
                        archivo = Request.Files[i];
                        br = new BinaryReader(archivo.InputStream);
                        if (archivo.ContentLength > 0)
                        {
                            sgcDB.addDocumentoAdjunto(Convert.ToInt32(idCorreo), archivo.ContentType, archivo.ContentLength, br.ReadBytes(Convert.ToInt32(archivo.InputStream.Length)), archivo.FileName);
                        }
                    }
                }
                #endregion

                return RedirectToAction("Exito", new { tipo = Convert.ToInt32(Request.Form["idTipoCorreo"]) });
            }

            List<TipoCorreo> tipos = sgcDB.TipoCorreos.Where(t => t.idTipoCorreo != BANDEJA_BORRADOS && t.idTipoCorreo != BANDEJA_TODOS).ToList();
            ViewBag.idTipoCorreo = new SelectList(tipos, "idTipoCorreo", "nombre", idTipoCorreo);
            ViewBag.medio = new SelectList(new[] 
            {
                new {idMedio = 0, nombre = "Electrónico"},
                new {idMedio = 1, nombre = "Físico"}
            }, "idMedio", "nombre", medio);
            return View();
        }
        #endregion

        #region Admin
        // Ruta: /Mail/Admin
        public ActionResult Admin()
        {
            if (Roles.IsUserInRole("Administrador"))
                ViewBag.Admin = true;
            else
                ViewBag.Admin = false;

            return View();
        }
        #endregion

        #region Reportes
        // Ruta: /Mail/Reportes
        public ActionResult Reportes()
        {
            ViewBag.UserName = new SelectList(sgcDB.aspnet_Users, "UserId", "UserName");
            return View();
        }

        // Ruta: /Mail/Reportes
        [HttpPost, ActionName("Reportes")]
        public ActionResult ReportesCompleted()
        {
            ModeloMail model = new ModeloMail();
            Guid idUsuario;

            if (Request.Form["UserName"] != null && Request.Form["UserName"] != "")
            {
                idUsuario = new Guid(Request.Form["UserName"]);
                model.Correo = sgcDB.Correos.Where(c => c.FK_idUsuario == idUsuario).OrderByDescending(c => c.fecha).ToPagedList(1, int.MaxValue);

                ViewBag.UserName = new SelectList(sgcDB.aspnet_Users, "UserId", "UserName", idUsuario);

                return View(model);
            }
            return View();
        }
        #endregion

        #region Estadisticas
        // Ruta: /Mail/Estadisticas
        public ActionResult Estadisticas()
        {
            ModeloEstadisticas model = new ModeloEstadisticas();
            model.totalCorreos = sgcDB.Correos.Count();
            model.totalUsuarios = sgcDB.aspnet_Users.Count();
            model.promCorreosXUsuario = sgcDB.Correos.Count()/sgcDB.aspnet_Users.Count();
            model.fechaUltimoCorreo = sgcDB.estadisticas().ElementAtOrDefault(0).Value.ToString();
            return View(model);
        }
        #endregion
    }
}
